package com.unswift.cloud.service.auth;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.cloud.adapter.system.auth.SystemResourceAdapter;
import com.unswift.cloud.adapter.system.auth.SystemResourceInputAdapter;
import com.unswift.cloud.adapter.system.auth.SystemResourceOutputAdapter;
import com.unswift.cloud.annotation.logger.OperatorLogger;
import com.unswift.cloud.enums.OperatorTypeEnum;
import com.unswift.cloud.enums.tree.TreeIconEnum;
import com.unswift.cloud.pojo.bo.system.resource.SystemResourceCreateBo;
import com.unswift.cloud.pojo.bo.system.resource.SystemResourceDeleteBo;
import com.unswift.cloud.pojo.bo.system.resource.SystemResourcePageBo;
import com.unswift.cloud.pojo.bo.system.resource.SystemResourceTreeBo;
import com.unswift.cloud.pojo.bo.system.resource.SystemResourceUpdateBo;
import com.unswift.cloud.pojo.bo.system.resource.SystemResourceViewBo;
import com.unswift.cloud.pojo.bo.system.resource.input.SystemResourceInputAuthBo;
import com.unswift.cloud.pojo.bo.system.resource.output.SystemResourceOutputAuthBo;
import com.unswift.cloud.pojo.dao.sql.Sql;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourceDataDo;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourceDeleteDo;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourceInsertDo;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourcePageDo;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourceSearchDo;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourceSingleDo;
import com.unswift.cloud.pojo.dao.system.resource.SystemResourceUpdateDo;
import com.unswift.cloud.pojo.dao.system.resource.input.SystemResourceInputUpdateBatchDo;
import com.unswift.cloud.pojo.dao.system.resource.input.SystemResourceInputUpdateBatchItemDo;
import com.unswift.cloud.pojo.dao.system.resource.output.SystemResourceOutputUpdateBatchDo;
import com.unswift.cloud.pojo.dao.system.resource.output.SystemResourceOutputUpdateBatchItemDo;
import com.unswift.cloud.pojo.vo.ListVo;
import com.unswift.cloud.pojo.vo.page.PageVo;
import com.unswift.cloud.pojo.vo.system.resource.SystemResourceCreateVo;
import com.unswift.cloud.pojo.vo.system.resource.SystemResourceDeleteVo;
import com.unswift.cloud.pojo.vo.system.resource.SystemResourcePageVo;
import com.unswift.cloud.pojo.vo.system.resource.SystemResourceTreeVo;
import com.unswift.cloud.pojo.vo.system.resource.SystemResourceUpdateVo;
import com.unswift.cloud.pojo.vo.system.resource.SystemResourceViewVo;
import com.unswift.cloud.pojo.vo.system.resource.input.SystemResourceInputAuthVo;
import com.unswift.cloud.pojo.vo.system.resource.input.SystemResourceInputViewVo;
import com.unswift.cloud.pojo.vo.system.resource.output.SystemResourceOutputAuthVo;
import com.unswift.cloud.pojo.vo.system.resource.output.SystemResourceOutputViewVo;
import com.unswift.cloud.service.BaseService;
import com.unswift.cloud.sql.system.resource.SystemResourceSql;
import com.unswift.cloud.utils.LoggerUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.utils.StringUtils;

@Service
@Api(value="系统资源服务", author="liyunlong", date="2023-10-05", version="1.0.0")
public class SystemResourceService extends BaseService{
	
	@Autowired
	@ApiField("系统资源公共服务")
	private SystemResourceAdapter systemResourceAdapter;
	@Autowired
	@ApiField("系统自定义sql")
	private SystemResourceSql systemResourceSql;
	@Autowired
	@ApiField("系统资源入参公共服务")
	private SystemResourceInputAdapter systemResourceInputAdapter;
	@Autowired
	@ApiField("系统资源出参公共服务")
	private SystemResourceOutputAdapter systemResourceOutputAdapter;
	
    @ApiMethod(value="查询系统资源树数据", params=@ApiField("树查询对象"), returns=@ApiField("包含查询数据的树对象"))
    public SystemResourceTreeVo findTreeList(SystemResourceTreeBo searchBo){
        SystemResourceSearchDo search=new SystemResourceSearchDo();
        Sql sql=Sql.createSql();
        if(ObjectUtils.isNotEmpty(searchBo.getName())){
            sql.addWhere(Sql.LOGIC_AND, "name_", Sql.COMPARE_LIKE, "concat('%',"+Sql.sqlValue(searchBo.getName())+",'%')");
        }
        sql.addOrderBy("sort_", Sql.ORDER_BY_ASC);
        search.setSql(sql);
        SystemResourceTreeVo root=new SystemResourceTreeVo(-1L, "资源树", true, false);
        root.setIcon(TreeIconEnum.AUTHORIZE.getKey());
        List<SystemResourceDataDo> list = systemResourceAdapter.findList(search);
        if(ObjectUtils.isNotEmpty(list)) {
        	String spreadPath=null;
        	if(ObjectUtils.isNotEmpty(searchBo.getSpreadId())){
        		SystemResourceDataDo spreadResource=systemResourceAdapter.findById(searchBo.getSpreadId());
        		if(ObjectUtils.isNotEmpty(spreadResource)) {
        			spreadPath=spreadResource.getParentPath();
        		}
        	}
            Set<Long> ids=list.stream().map(r -> r.getId()).collect(Collectors.toSet());
			systemResourceAdapter.findParent(list, ids);
        	List<SystemResourceDataDo> rootList=list.stream().filter(r -> r.getType().equals("platform") && ObjectUtils.isEmpty(r.getParentId())).collect(Collectors.toList());
        	if(ObjectUtils.isEmpty(rootList)){
        		return root;
        	}
        	if(rootList.size()==1) {
        		root.setId(rootList.get(0).getId());
        		root.setTitle(rootList.get(0).getName());
        		systemResourceAdapter.parseResourceToTree(list, root, spreadPath);
        	} else {
        		List<SystemResourceTreeVo> childList=new ArrayList<SystemResourceTreeVo>();
        		SystemResourceTreeVo childNode;
        		for (SystemResourceDataDo resource : rootList) {
        			childNode=new SystemResourceTreeVo(resource.getId(), resource.getName());
        			if(ObjectUtils.isNotEmpty(spreadPath) && StringUtils.contains(spreadPath, resource.getId()+"", ".")){
        				childNode.setSpread(true);
        			}
        			childList.add(childNode);
        			systemResourceAdapter.parseResourceToTree(list, childNode, spreadPath);
				}
        		root.setChildren(childList);
        	}
        }
        return root;
    }
	@ApiMethod(value="查询系统资源分页数据", params=@ApiField("分页对象，包含分页信息及查询条件"), returns=@ApiField("包含查询数据的分页对象"))
	public PageVo<SystemResourcePageVo> findPageList(SystemResourcePageBo searchBo){
		SystemResourcePageDo search=this.convertPojo(searchBo, SystemResourcePageDo.class);//将Bo转换为Do
		search.setFirstSize((search.getCurrPage()-1)*search.getPageSize());
		PageVo<SystemResourceDataDo> page=systemResourceAdapter.findPageList(search);//将Do转换为Vo
		return this.convertPage(page, SystemResourcePageVo.class);
	}
	
	@ApiMethod(value="查询系统资源详情", params=@ApiField("详情业务实体，包含id字段"), returns=@ApiField("系统资源详情数据"))
	public SystemResourceViewVo view(SystemResourceViewBo viewBo){
		SystemResourceSingleDo search=this.convertPojo(viewBo, SystemResourceSingleDo.class);
		systemResourceAdapter.addSelectColumn(search, systemResourceSql.findParentNameSql(), "parentName");
		SystemResourceDataDo single=systemResourceAdapter.findSingle(search);
		SystemResourceViewVo view=this.convertPojo(single, SystemResourceViewVo.class);
		if(ObjectUtils.isNotEmpty(view)) {
			view.setInputList(this.convertPojoList(systemResourceInputAdapter.findByResourceId(view.getId()), SystemResourceInputViewVo.class));
			view.setOutputList(this.convertPojoList(systemResourceOutputAdapter.findByResourceId(view.getId()), SystemResourceOutputViewVo.class));
		}
		return view;//将Do转换为Vo
	}

	@OperatorLogger(type = OperatorTypeEnum.CREATE)
	@ApiMethod(value="创建系统资源", params=@ApiField("创建的业务实体"), returns=@ApiField("创建结果{0：未创建，1：已创建}"))
	public SystemResourceCreateVo create(SystemResourceCreateBo createBo){
		LoggerUtils.setModule(systemResourceAdapter.getModule());//设置日志所属模块
		SystemResourceInsertDo insert=this.convertPojo(createBo, SystemResourceInsertDo.class);//将Bo转换为Do
		insert.setParentPath(systemResourceAdapter.getCompletePath(insert.getParentId()));//设置资源path
		systemResourceAdapter.setInsertDefault(insert);//设置Default
		int result=systemResourceAdapter.save(insert, true);
		LoggerUtils.setId(insert.getId());//创建日志需要设置数据id
		return new SystemResourceCreateVo(result);
	}
	
	@Transactional("systemTransactionManager")
	@OperatorLogger(type = OperatorTypeEnum.UPDATE)
	@ApiMethod(value="更新系统资源", params=@ApiField("更新的业务实体"), returns=@ApiField("更新结果{0：未创建，1：已创建}"))
	public SystemResourceUpdateVo update(SystemResourceUpdateBo updateBo){
		LoggerUtils.setModule(systemResourceAdapter.getModule());//设置日志所属模块
		SystemResourceDataDo currResource=systemResourceAdapter.findById(updateBo.getId());
		LoggerUtils.setOriginalData(currResource);//设置日志原数据对象
		
		SystemResourceUpdateDo update=this.convertPojo(updateBo, SystemResourceUpdateDo.class);//将Bo转换为Do
		int result=systemResourceAdapter.update(update, true);
		systemResourceInputAdapter.deleteByResourceId(update.getId());//删除入参
		systemResourceOutputAdapter.deleteByResourceId(update.getId());//删除出参
		if(ObjectUtils.isNotEmpty(update.getOpenInput()) && update.getOpenInput()) {//保存入参
			List<SystemResourceInputUpdateBatchItemDo> inputList = this.convertPojoList(updateBo.getInputList(), SystemResourceInputUpdateBatchItemDo.class);
			int sort=1;
			for (SystemResourceInputUpdateBatchItemDo input : inputList) {
				input.setResourceId(update.getId());
				input.setSort(sort);
				sort++;
			}
			systemResourceInputAdapter.saveBatch(new SystemResourceInputUpdateBatchDo(inputList), false);
		}
		if(ObjectUtils.isNotEmpty(update.getOpenOutput()) && update.getOpenOutput()) {//保存出参
			List<SystemResourceOutputUpdateBatchItemDo> outputList = this.convertPojoList(updateBo.getOutputList(), SystemResourceOutputUpdateBatchItemDo.class);
			int sort=1;
			for (SystemResourceOutputUpdateBatchItemDo output : outputList) {
				output.setResourceId(update.getId());
				output.setSort(sort);
				sort++;
			}
			systemResourceOutputAdapter.saveBatch(new SystemResourceOutputUpdateBatchDo(outputList), false);
		}
		return new SystemResourceUpdateVo(result);
	}
	
	@Transactional("systemTransactionManager")
	@OperatorLogger(type = OperatorTypeEnum.DELETE)
	@ApiMethod(value="删除系统资源", params=@ApiField("删除业务实体，包含id字段"), returns=@ApiField("删除结果{0：未创建，1：已创建}"))
	public SystemResourceDeleteVo delete(SystemResourceDeleteBo deleteBo){
		LoggerUtils.setModule(systemResourceAdapter.getModule());//设置日志所属模块
		SystemResourceDeleteDo delete=this.convertPojo(deleteBo, SystemResourceDeleteDo.class);//将Bo转换为Do
		ExceptionUtils.trueException(systemResourceAdapter.existsChild(deleteBo.getId()), "resource.exists.childs");//存在孩子不允许删除
		int result=systemResourceAdapter.delete(delete);
		systemResourceInputAdapter.deleteByResourceId(delete.getId());//删除入参
		systemResourceOutputAdapter.deleteByResourceId(delete.getId());//删除出参
		return new SystemResourceDeleteVo(result);
	}
	
	@ApiMethod(value="根据权限key获取入参列表", params = {@ApiField("权限key Bo对象")}, returns = @ApiField("入参列表"))
	public ListVo<SystemResourceInputAuthVo> findInputList(SystemResourceInputAuthBo searchBo){
		return new ListVo<SystemResourceInputAuthVo>(systemResourceInputAdapter.getInputListByAuthKey(searchBo.getAuthKey()));
	}
	
	@ApiMethod(value="根据权限key获取出参列表", params = {@ApiField("权限key Bo对象")}, returns = @ApiField("出参列表"))
	public ListVo<SystemResourceOutputAuthVo> findOutputList(SystemResourceOutputAuthBo searchBo){
		return new ListVo<SystemResourceOutputAuthVo>(systemResourceOutputAdapter.getOutputListByAuthKey(searchBo.getAuthKey()));
	}
}
